package com.fulu.game.bi.redis.service;

import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.*;
import java.util.concurrent.TimeUnit;

public interface RedisOpenService {

    /**
     * 获取某个key的值
     *
     * @param key
     * @return
     */
    String get(String key);

    /**
     * 获取某个key的过期时间
     *
     * @param key
     * @return
     */
    Long getExpireTime(String key);


    /**
     * 统计bit位为1的总数
     *
     * @param key
     */
    Long bitCount(final String key);


    /**
     * 添加hyperLogLog
     *
     * @param key
     * @param vals
     * @return
     */
    boolean hyperLogLogAdd(String key, Object... vals);

    /**
     * 添加hyperLogLog并设置有效期
     *
     * @param key
     * @param time
     * @param vals
     * @return
     */
    boolean hyperLogLogAdd(String key, Long time, Object... vals);

    /**
     * 计算hyperLogLog大小
     *
     * @param keys
     * @return
     */
    Long hyperLogLogSize(String keys);


    Long bitOp(final RedisStringCommands.BitOperation op, final String destination, final String... keys);


    /**
     * 添加一个BitSet
     *
     * @param key
     * @param val
     */
    void bitSet(String key, long val, boolean flag);

    /**
     * 添加一个BitSet,默认为true
     *
     * @param key
     * @param val
     */
    void bitSet(String key, long val);

    /**
     * 判断bitSet值(Value是在bit中存在)
     *
     * @param key
     * @param val
     * @return
     */
    Boolean getBitSet(String key, long val);

    /**
     * 设置某个key的值
     *
     * @param key
     * @param value
     */
    void set(String key, String value);

    /**
     * 设置某个key的值及保存时间
     *
     * @param key
     * @param value
     * @param time
     */
    void set(String key, String value, long time);

    /**
     * 设置某个key的值及保存时间
     *
     * @param key
     * @param value
     * @param time
     */
    void set(String key, String value, long time, TimeUnit unit);

    /**
     * 设置某个key的值
     *
     * @param key
     * @param value
     * @param isPerpetual 是否永久保存（true：是；false：否）
     */
    void set(String key, String value, boolean isPerpetual);

    /**
     * 根据key设置某个hash的值
     *
     * @param key
     * @param hash
     * @param value
     */
    void hset(String key, String hash, Object value);

    /**
     * 根据key设置某个hash的值
     *
     * @param key
     * @param hash
     * @param value
     * @param isPerpetual 是否永久保存（true：是；false：否）
     */
    void hset(String key, String hash, Object value, boolean isPerpetual);

    /**
     * 根据key设置某个hash的值及存活时间
     *
     * @param key
     * @param hash
     * @param value
     * @param time
     */
    void hset(String key, String hash, Object value, long time);

    /**
     * 根据key设置hashtable的值
     *
     * @param key
     * @throws Exception
     */
    void hset(String key, Map<String, Object> map);

    /**
     * 根据key设置hashtable的值
     *
     * @param key
     * @param map
     * @param isPerpetual 是否永久保存（true：是；false：否）
     */
    void hset(String key, Map<String, Object> map, boolean isPerpetual);

    /**
     * 根据key设置hashtable的值
     *
     * @param key
     * @param time
     * @throws Exception
     */
    void hset(String key, Map<String, Object> map, long time);

    long hdel(String key, Object... hashKeys);

    /**
     * 根据key删除某个hash的值
     *
     * @param key
     * @param hash
     * @return
     */
    String hdel(String key, String hash);

    /**
     * 自增
     *
     * @param key
     * @param hashkey
     * @param incr
     * @return
     */
    Double hincr(String key, String hashkey, double incr);

    void expire(String key, long time, TimeUnit timeUnit);


    void expire(String key, long time);

    void expireAt(String key, Date date);

    /**
     * 根据key获取某个hash的值
     *
     * @param key
     * @param hash
     * @return
     */
    String hget(String key, String hash);

    /**
     * 根据key获取整个hashtable
     *
     * @param key
     * @return
     */
    Map<String, Object> hget(String key);

    /**
     * 根据key删除整个hashtable
     *
     * @param key
     * @return
     */
    void delete(String key);

    void delete(Collection keys);

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    boolean hasKey(String key);

    /**
     * redis锁
     *
     * @param key
     * @param expireTime
     */
    boolean lock(String key, long expireTime);

    /**
     * 释放锁
     *
     * @param key
     */
    void unlock(String key);

    /**
     * 存储时间间隔
     *
     * @param key
     * @param time
     */
    void setTimeInterval(String key, long time);

    /**
     * 判断时间间隔
     *
     * @param key
     * @return
     */
    Boolean isTimeIntervalInside(String key);

    /**
     * 获取listOps来操作list
     *
     * @param key
     * @return
     */
    <T, S> BoundListOperations<T, S> getListOps(String key);

    /**
     * 初始化list
     *
     * @param <T>
     * @return
     */
    <T> long listForInit(String key, List<T> values);

    /**
     * 向list某个下标插入元素
     *
     * @param key
     * @param index
     * @param value
     * @param <T>
     */
    <T> void listSetForIndex(String key, int index, T value);


    <T> void listSetForRightPush(String key, T value);

    /**
     * 查询list的大小
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> long listForSize(String key);

    /**
     * 查询list所有元素
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> List<T> listForAll(String key);

    /**
     * 查询list所有元素
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> List<T> listForAll(String key, RedisSerializer<T> redisSerializer);

    /**
     * 查询list索引index元素
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> T listGetForIndex(String key, int index);

    /**
     * 查询list range 元素
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> List<T> listForRange(String key, int startIndex, int endIndex);

    /**
     * 往SET中插入元素
     *
     * @param key
     * @param value
     * @param <T>
     */
    <T> long setForAdd(String key, T value);

    long setForInit(String key, List<String> value);

    /**
     * true: set原本不存在或中原来没有这个值 false : set存在且其中本来包含该值
     */
    boolean addSetValueCache(String key, String value);

    /**
     * 在SET中删除元素
     *
     * @param key
     * @param value
     * @param <T>
     */
    <T> long setForDel(String key, T value);

    /**
     * 查询SET的size
     *
     * @param key
     */
    long setForSize(String key);

    /**
     * 查询SET的所有元素
     *
     * @param key
     */
    <T> Set<T> setForAll(String key);

    /**
     * 随机出栈集合的元素
     *
     * @param key 集合key
     * @return 取出的元素
     */
    String randomPop(String key);

    /**
     * 判断元素是否存在
     *
     * @param key    集合的key
     * @param member 集合是否存在的member
     * @return 是否存在的结果
     */
    boolean isMember(Object key, Object member);

    /**
     * 往ZSET中插入元素
     *
     * @param key
     * @param value
     * @param score 排序分数
     * @param <T>
     */
    <T> boolean zsetForAdd(String key, T value, double score);

    /**
     * 往ZSET中插入元素(按照集合元素size来定义顺序)
     *
     * @param key
     * @param value
     * @param <T>
     */
    <T> boolean zsetForAdd(String key, T value);

    /**
     * 往ZSET中插入元素(按照指定分数来定义顺序)
     *
     * @param key
     * @param value
     * @param score
     * @param <T>
     * @return
     */
    <T> boolean zsetForAdd(String key, T value, long score);

    /**
     * 返回元素在集合的排名
     *
     * @param key
     * @param o
     * @return
     */
    Long zsetRank(Object key, Object o);

    /**
     * 返回元素在集合的排名
     *
     * @param key
     * @param o
     * @return
     */
    Long zsetReverseRank(Object key, Object o);

    /**
     * 在ZSET中删除元素
     *
     * @param key
     * @param value
     * @param <T>
     */
    <T> long zsetForDel(String key, T value);

    /**
     * 删除ZSET指定SCORE范围内的元素
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    Long zsetRemoveRangeByScore(Object key, double start, double end);

    /**
     * 查询SET的size
     *
     * @param key
     */
    long zsetForSize(String key);

    /**
     * 获取ZSet全部元素
     *
     * @param key
     * @param reverse 是否需要相反排序获取元素
     * @param <T>
     * @return
     */
    <T> Set<T> zsetForAll(String key, Boolean reverse);

    /**
     * 移除zset中的元素
     *
     * @param key
     * @param startIndex
     * @param endIndex
     * @return
     */
    Long zsetRemoveRange(String key, Integer startIndex, Integer endIndex);

    /**
     * 根据score获取zset
     * @param key
     * @param minScore
     * @param maxScore
     * @param isReverse
     * @param <T>
     * @return
     */
    <T> Set<T> zsetRangeByScore(String key, Double minScore, Double maxScore, Boolean isReverse);

    /**
     * 根据score和limit获取zset
     * @param key
     * @param minScore
     * @param maxScore
     * @param offset
     * @param count
     * @param isReverse
     * @param <T>
     * @return
     */
    <T> Set<T> zsetRangeByScore(String key, Double minScore, Double maxScore, Long offset, Long count, Boolean isReverse);

    /**
     * 根据score和limit批量获取zset
     * @param <T>
     * @param keys
     * @param minScore
     * @param maxScore
     * @param offset
     * @param count
     * @param isReverse
     * @return
     */
    <T> List<LinkedHashSet<T>> zsetRangeByScorePipelined(List<String> keys, Double minScore, Double maxScore, Long offset, Long count, Boolean isReverse);

    /**
     * 获取zset倒序排名
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    Set<TypedTuple<String>> getZsetCacheValuesScoresReverse(String key, Long start, Long end);


    Set zsetReverseRangeByScore(String key, double min, double max);

    /**
     * 增加zset中元素的score值
     *
     * @param key
     * @param member
     * @param increasedScore
     * @return
     */
    boolean incrementByZsetCache(String key, String member, Long increasedScore);

    /**
     * 增加zset中元素的score值
     *
     * @param key
     * @param member
     * @param increasedScore
     * @return
     */
    boolean incrementByZsetCache(String key, String member, double increasedScore);

    /**
     * 查询zset中score满足范围的成员数量（包含min，max）
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    Long zsetForScoreCount(Object key, double min, double max);

    /**
     * 获取zset中某个值的score
     */
    Double getZsetCacheValueScore(String key, String value);

    /**
     * blocking 一直阻塞直到队列里边有数据
     * remove and get last item from queue:BRPOP
     *
     * @return
     */
    <T> T takeFromTail(String key, int timeout) throws InterruptedException;

    /**
     * blocking 一直阻塞直到队列里边有数据
     * remove and get first item from queue:BLPOP
     *
     * @return
     */
    <T> T takeFromHead(String key, int timeout) throws InterruptedException;

    /**
     * 自增
     *
     * @param key
     * @return
     */
    long incr(String key);

    /**
     * 递增
     *
     * @param key
     * @param delta 递增因子，必须大于0
     * @return
     */
    long incr(String key, long delta);

    /**
     * 自减
     *
     * @param key 键
     * @return
     */
    long decr(String key);

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return
     */
    long decr(String key, long delta);

    /**
     * 获取Integer类型的值
     *
     * @param key
     * @return
     */
    Integer getInteger(String key);

    List hgetAllPipelined(List<String> keys);

    List getAllPipelined(List<String> keys);

    List smembersPipelined(List<String> keys);

    /**
     * 通配符查找redis的key: 建议采用scan方法.
     * @param parttern
     * @return
     */
    @Deprecated
    Set<String> keys(String parttern);

    /**
     * redis锁
     *
     * @param key
     * @param millisecondsExpireTime
     */
    boolean tryLockMilliseconds(String key, long millisecondsExpireTime);

    /**
     * 加锁
     *
     * @param key key值
     * @return 是否获取到
     */
    boolean disLock(String key, long expire);

    BoundListOperations boundListOps(String redisKey);

    BoundHashOperations boundHashOps(String redisKey);

    List<String> mget(List<String> keys);

    /**
     * 大数据量时可以替代keys, 避免阻塞.
     * scan命令详细说明参考: <code>http://doc.redisfans.com/key/scan.html</code>
     * @param match 和 KEYS 命令一样， 增量式迭代命令也可以通过提供一个 glob 风格的模式参数， 让命令只返回和给定模式相匹配的元素，
     *              这一点可以通过在执行增量式迭代命令时， 通过给定 MATCH <b>pattern</b> 参数来实现。
     *  默认指定了count,虽然增量式迭代命令不保证每次迭代所返回的元素数量， 但我们可以使用 COUNT 选项， 对命令的行为进行一定程度上的调整。
     *              基本上， COUNT 选项的作用就是让用户告知迭代命令， 在每次迭代中应该从数据集里返回多少元素。
     *              在迭代一个足够大的、由哈希表实现的数据库、集合键、哈希键或者有序集合键时，
     *              如果用户没有使用 MATCH 选项， 那么命令返回的元素数量通常和 COUNT 选项指定的一样，
     *              或者比 COUNT 选项指定的数量<b>稍多一些</b>。
     * @return
     */
    Set<String> scan(String match);
}

